#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author : liuyu
# date : 2018/11/2 0002


import socket, uuid
import time,os,pathlib
from .shellcmds import use_user_pass,SSHConnection

'''
1.通过ssh 通道执行命令
use_user_pass(hostip,port,user,passwd,cmdstrs)

2.通过ansible 执行命令
execshell([{"host": "10.1.41.220","port": 6553,"user": "root","password": "root"}], "uptime")

'''


class Remote_Exec(object):

    def __init__(self, host, port, user, passwd, cmdstrs, flag="shell", timeout=1):
        '''

        :param host:        remote_host_ip
        :param port:        remote_port
        :param user:        remote_user
        :param passwd:      remote_password
        :param cmdstrs:     remote_commands
        :param flag:        shell: user ssh to exec cmd   ansible: user ansible to exec cmd
        :param timeout:     default is 1 ,is use 1 s to check remote_host is online
        '''

        self.host = host
        self.port = port
        self.user = user
        self.passwd = passwd
        self.cmdstrs = pathlib.PurePath(cmdstrs).as_posix()
        self.flag = flag
        self.timeout = timeout

    def remote_host_check_online(self):
        result = {}
        sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sk.settimeout(self.timeout)
        try:
            sk.connect((self.host, self.port))
        except Exception as e:
            result["message"] = "SSH Port Connection refused"
            result["code"] = 1
        sk.close()
        return [{self.host: result}]

    def download(self,remotepath, localpath):
        try:
            conn = SSHConnection(self.host, self.port, self.user, self.passwd,)
        except Exception as e:
            return [{self.host: {
                'message': str(e),
                'code': 1,
                'results': {}
            }}]
        conn.download(remotepath, localpath)

    def fileisexists(self,context):
        shellcmdlist = self.cmdstrs.split(" ")
        if shellcmdlist[0] == "sh" or shellcmdlist[0] == "bash" or "python" in shellcmdlist[0]:
            cmdstrs="[ -e {} ] && echo FILEXISTS".format(shellcmdlist[1])
            results = use_user_pass(self.host, self.port, self.user, self.passwd, cmdstrs)
            message = results[0].get(self.host).get("results").get("message")
            if message != "FILEXISTS":
                localfile=self.makescripts(context)
                self.put(localfile,shellcmdlist[1])
                time.sleep(1)
                os.unlink(localfile)

    def makescripts(self,context):
        BASE_DIR = os.path.dirname(os.path.abspath(__file__))
        shellname = os.path.join(BASE_DIR,  str(uuid.uuid1()))
        context = context.replace('\r', '').encode(encoding="utf-8")
        with open(shellname, 'wb') as f:
            f.write(context)
        return shellname

    def put(self, localpath,remotepath):
        try:
            conn = SSHConnection(self.host, self.port, self.user, self.passwd,)
        except Exception as e:
            return [{self.host: {
                'message': str(e),
                'code': 1,
                'results': {}
            }}]
        conn.put(localpath, remotepath)


    def run(self, screen=0,autoexit=0,context=""):
        '''

        :param screen:    0:close
        :param autoexit:    o:close
        :return:
        '''

        self.fileisexists(context)
        check_data = self.remote_host_check_online()
        if check_data[0].get(self.host).get("code") == 1:
            check_data[0]["type"] = self.flag
            return check_data
        results = []

        if autoexit:
            endstr="\\r\\rexit\\r"
        else:
            endstr="\\r\\r"


        if self.flag == "ansible":
            try:
                from .ansible_api import execshell
                if screen:
                    screenuuid = "{}_{}".format(uuid.uuid3(uuid.NAMESPACE_X500, self.cmdstrs), uuid.uuid1())
                    CMDSTRS = "ps aux | \grep 'SCREEN -dmS {0}' |grep -v 'grep SCREEN -dmS {0}' |awk -F'SCREEN' '{{print $2}}'|awk '{{print $2}}'".format(
                        screenuuid.split("_")[0])
                    results = use_user_pass(self.host, self.port, self.user, self.passwd, CMDSTRS)
                    if results[0][self.host]["code"] == 0 and results[0][self.host]["results"]["code"] == 0 and \
                            results[0][self.host]["results"]["message"] in screenuuid:
                        cmdstrs = "screen -dmS {} -L -t {}".format(screenuuid, screenuuid)
                        results = use_user_pass(self.host, self.port, self.user, self.passwd, cmdstrs)

                        if results[0][self.host]["code"] == 0 and results[0][self.host]["results"]["code"] == 0:
                            cmdstrs = "screen -x -RS {} -p 0 -X stuff '{} {}'".format(screenuuid, self.cmdstrs,
                                                                                      "\rexit\r")
                            results = use_user_pass(self.host, self.port, self.user, self.passwd, cmdstrs)
                            results[0][self.host]["screenuuid"] = str(screenuuid)
                        else:
                            results[0][self.host]["screenuuid"] = results[0][self.host]["results"]["message"]
                else:
                    results = execshell(
                        [{"host": self.host, "port": self.port, "user": self.user, "password": self.passwd}],
                        self.cmdstrs)
            except Exception as e:
                results[0]["message"] = str(e)
                results[0]["code"] = 1
        else:
            if screen:
                screenuuid = "{}_{}".format(uuid.uuid3(uuid.NAMESPACE_X500, self.cmdstrs), uuid.uuid1())
                CMDSTRS = "ps aux | \grep 'SCREEN -dmS {0}' |grep -v 'grep SCREEN -dmS {0}' |awk -F'SCREEN' '{{print $2}}'|awk '{{print $2}}'".format(
                    screenuuid.split("_")[0])
                results = use_user_pass(self.host, self.port, self.user, self.passwd, CMDSTRS)
                time.sleep(1)
                if results[0][self.host]["code"] == 0 and results[0][self.host]["results"]["code"] == 0 and \
                        results[0][self.host]["results"]["message"] in screenuuid:
                    cmdstrs = "screen -dmS {0} -L -t {0}".format(screenuuid)
                    results = use_user_pass(self.host, self.port, self.user, self.passwd, cmdstrs)
                    if results[0][self.host]["code"] == 0 and results[0][self.host]["results"]["code"] == 0:
                        cmdstrs = "screen -x -RS {} -p 0 -X stuff \"{} {}\"".format(screenuuid, self.cmdstrs, endstr)
                        # print(cmdstrs)
                        results = use_user_pass(self.host, self.port, self.user, self.passwd, cmdstrs)
                        results[0][self.host]["screenuuid"] = str(screenuuid)
                else:
                    results[0][self.host]["screenuuid"] =results[0][self.host]["message"]
            else:
                results = use_user_pass(self.host, self.port, self.user, self.passwd, self.cmdstrs)
        results[0][self.host]["type"] = self.flag
        return results


    def autorun(self, screen=0,autoexit=0,context=""):
        results = self.run(screen,autoexit,context)
        resultslist=[]
        for result in results:
            print(result)
            for k,v in result.items():
                try:
                    message = v.get("results").get("message")
                    if message == "bash: screen: command not found" or "screen: command not found" in message:
                        oldcmdstr = self.cmdstrs
                        self.cmdstrs = "yum install -y screen"
                        self.run(0,0)
                        self.cmdstrs=oldcmdstr
                        result = self.run(screen, autoexit,context)[0]
                except:
                    pass
            resultslist.append(result)
        return resultslist


